﻿using System;
using System.Web;

using Yawf.Security;
using Yawf.Security.Entities;
using Yawf.Core.Exceptions;
using Yawf.Core.Logs;
using Yawf.Web;
using Yawf.Web.Managers;
using Yawf.Web.Managers.Entities;
using Yawf.Web.Utils;

namespace Yawf.Web.HttpHandlers {
	public class MVCController {
		private IAuthenticationManager authenticationManager;
		private IModelInvokerManager modelManager;
		private IModelViewerManager viewManager;
		private IErrorManager errorManager;
		private String resourceLocation;
		private String webPartPageVariableName;

		public IAuthenticationManager AuthenticationManager { get { return authenticationManager; } set { authenticationManager = value; } }
		public IModelInvokerManager ModelManager { get { return modelManager; } set { modelManager = value; } }
		public IModelViewerManager ViewManager { get { return viewManager; } set { viewManager = value; } }
		public IErrorManager ErrorManager { get { return errorManager; } set { errorManager = value; } }
		public String ResourceLocation { get { return resourceLocation; } set { resourceLocation = value; } }
		public String WebPartPageVariableName { get { return webPartPageVariableName; } set { webPartPageVariableName = value; } }

		/// <summary>
		/// Sets output content type and needed headers if the resource is to be downloaded
		/// </summary>
		/// <param name="view">View object to get output data from</param>
		/// <param name="response">Response object to set output parameters into</param>
		private void PrepareContentOutput(View view,ResponseWrapper response){
			String[] names;
			String fileName;
		
			response.Response.ContentType = view.ContentType;
			if (view.Downloadable){
				names = view.Resource.Split('/');
				fileName = names[names.Length - 1];
				fileName = fileName.Replace(".xml",view.Extension);
				response.Response.AddHeader("Content-Disposition","attachment; filename=" + fileName);				
			}
		}							// PrepareContentOutput
	
		/// <summary>
		/// Here we really handle the request/response cycle
		/// </summary>
		/// <param name="context">HttpContext to use</param>
		public void ProcessRequest(HttpContext context) {
			ResponseWrapper responseWrapper;
			RequestWrapper requestWrapper;
			View view;
			IUser currUser = null;
			String resourcePath;

			requestWrapper = new RequestWrapper(context.Request,context.Session);
			responseWrapper = new ResponseWrapper(context.Response);
			resourcePath = requestWrapper.GetResourcePath(WebPartPageVariableName);
			if (resourcePath == null || resourcePath == "" || resourcePath == "/") {
				resourcePath = "~/index.xml";
			}
			resourcePath = ResourceLocation  + resourcePath;

			try {
				// Check authorization first
				currUser = requestWrapper.GetUser();
				if (this.AuthenticationManager == null){
					throw new YawfException("AuthenticationManager no asignado a controlador de MVC(clase MVCController)");
				}
				if (!this.AuthenticationManager.HasPermisssion(currUser,resourcePath)) {
					throw new AuthorizationException(currUser,resourcePath);
				}

				// Do application logic for this path info
				ModelManager.ProcessModel(requestWrapper,responseWrapper,resourcePath,currUser);

				// Check for user again, cause model may have set current user
				if (currUser == null) {
					currUser = requestWrapper.GetUser();
				}

				// Prepare headers and content type
				view = new View(resourcePath);
				PrepareContentOutput(view,responseWrapper);

				// Do present view
				ViewManager.ProcessView(requestWrapper,responseWrapper,view,currUser);
			} catch (YawfException e) {
				// Get error handler and handle error
				if (ErrorManager != null) {
					ErrorManager.HandleError(requestWrapper,responseWrapper,resourcePath,currUser,e);
				} else {
					Log.ExceptionMessage(this.GetType(),"No Error manager defined, printing error to response,Root cause[" + e + "]",e);
					responseWrapper.Writer.WriteLine("Exception [" + e + "]");
				}
			} catch (Exception e) {
				Log.ExceptionMessage(this.GetType(),"Fatal error when handling buisness-view XML file [" + resourcePath + "],Root cause[" + e + "]",e);
				throw e;
			}
		}
	}
}
